#include "common.h"
#include "memory/cache.h"
#include "burst.h"
#include "stdlib.h"

uint32_t dram_read(hwaddr_t addr, size_t len);
void call_ddr3_read(hwaddr_t,void *);
void call_ddr3_write(hwaddr_t,void *,uint8_t *);

void init_cache()
{
    int i;
    for(i=0;i<CACHE_SIZE / CACHE_BLOCK;i++)
    {
        cache[i].valid = false;
        cache[i].tag = 0;
        memset(cache[i].byte,0,CACHE_BLOCK);  
    }
    cnt = 0;
}
//初始化cache

uint32_t cache_read(hwaddr_t addr)
{
    uint32_t set = (addr >>6)&0x7f;
    //取出地址中set的部分（右移block位并 & 1111111），set = 7 byte (set = 2^s = 128), offset = 6 byte (block = 2^e = 64)
    bool hit = false;
    int i;
    for(i = set *E;i<(set+1)*E;i++)//找到相应的set所在
    {
        if(cache[i].tag == (addr >> 13)&& cache[i].valid)
        {
            hit = true;
            cnt += 2;
            break;
        }
    }
    if(!hit)//缓存里边找不到
    {
        for(i = set *E;i<(set+1)*E;i++)
        {
            if(!cache[i].valid)//如果这里是空的就从这里退出
            break;
        }
        if(i == (set+1)*E)//如果循环到最后还没有空位就执行随机替换
        {
            srand(0);
            i = set*E +rand()%E;
        }
        cache[i].valid = true;
        cache[i].tag = addr >>13;
        int j;
        uint32_t block = (addr>>6) << 6;//取出block
        for(j=0;j<BURST_LEN;j++)
        {
            call_ddr3_read(block + j *BURST_LEN,cache[i].byte +j*BURST_LEN);
        }
        cnt += 200;//这个cnt变量时用来观察成功实现了cache之后，运行
        //用户程序所需要的时间
    }
    return i;
}

void cache_write(hwaddr_t addr , size_t len,uint32_t data)
{
    uint32_t set = (addr >>6)&0x7f;
    uint32_t offset = addr & (CACHE_BLOCK -1);
    int i;
    bool hit = false;
    for (i = set * E; i < (set + 1) * E; i++) {
        if (cache[i].tag == (addr >> 13) && cache[i].valid) {
            hit = true;
            break;
        }
    }//看看中没中
    if(hit){
        memcpy(cache[i].byte +offset,&data,len);
    }
    else{
        i = cache_read(addr);//从内存中找到数据对应的位置
        memcpy(cache[i].byte +offset,&data,len);
    }
}